﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Windows.Forms;

namespace LightEngine
{
    namespace DataControlling
    {
        /// <Описание перечисления public enum LogType>
        /// Перечисление содержит типы сообщений лога
        /// WarningMessage - сообщения предупреждения/неисправности
        /// OrdinaryMessage - обычное сообщение о рядовом событии
        /// SuccessMessage - сообщение об успешном выполнении операци...
        /// InformationMessage - сообщение информационного характера (детализация операций)
        /// HighlightedMessage - выдленное (например, цветом) сообщение
        /// </Описание перечисления public enum LogType>
        public enum LogType
        {
            WarningMessage = 0,
            OrdinaryMessage = 1,
            SuccessMessage = 2,
            InformationMessage = 3,
            HighlightedMessage = 4
        }

        /// <описание структуры public struct TextAttributtes>
        /// Версия структуры 1.0
        /// Автор(ы): Ушаков Михаил
        /// Структура предназначена для хранения текста лога и атрибутов рисования текста
        /// изпользуя типы данных GDI+ (пространство имен System.Drawing)
        /// Элементы структуры:
        /// 1. Константы структуры:
        ///    отсутствуют.
        /// 2. Поля структуры:
        /// а) public StringBuilder LogText - текст лога, перед использованием экземпляра
        ///    структуры нужно использовать выделение памяти с помощью оператора new
        /// б) public LogType TypeOfLog - тип сообщения лога из перечисления LogType
        /// в) public Color TextColor - цвет текста лога
        /// г) public Font FontStyle - шрифт лога
        /// 3. Методы структуры:
        ///    отсутсвуют
        /// 4. Свойства и индексаторы структуры:
        ///    отсутствуют.
        /// </описание структуры public struct TextAttributtes>
        public struct TextAttributtes
        {
            public StringBuilder LogText;
            public LogType TypeOfLog;
            public Color TextColor;
            public Font FontStyle;
        }

        /// <описание класса public class NewLogEventsArgs : EventArgs>
        /// Версия класса 1.0
        /// Автор(ы): Ушаков Михаил
        /// Класс предназначен для описания события, возникающего при добавлении нового сообщения лога,
        /// этот класс используется как аргумент, описывающий событие.
        /// Элементы класса:
        /// 1. Константы класса:
        ///    отсутствуют.
        /// 2. Поля класса:
        /// а) private TextAttributtes LogMsg - сообщение лога с атрибутами
        /// 3. Методы класса:
        /// а) public NewLogEventsArgs(TextAttributtes NewLogMessage) конструктор, выполняющие построение
        ///    экземпляра класса
        /// 4. Свойства и индексаторы класса:
        /// а) свойство только для чтения, возвращает сообщение лога.
        /// </описание класса public class NewLogEventsArgs : EventArgs>
        public class NewLogEventsArgs : EventArgs
        {
            private TextAttributtes LogMsg;
            public NewLogEventsArgs(TextAttributtes NewLogMessage)
            {
                LogMsg = NewLogMessage;
            }

            public TextAttributtes LogMessage { get { return LogMsg; } }
        }

        /// <описание класса public class Logger>
        /// Версия класса 1.0
        /// Автор(ы): Ушаков Михаил
        /// Класс предназначен для описания события, возникающего при добавлении нового сообщения лога,
        /// этот класс используется как аргумент, описывающий событие.
        /// Элементы класса:
        /// 1. Константы класса:
        ///    отсутствуют.
        /// 2. Поля класса:
        /// а) private List<TextAttributtes> Logs - список логов с атрибутами
        /// б) private Dictionary<LogType, Color> LogMsgColors словарь соответствия типов логов и их цветов
        /// в) private Dictionary<LogType, Font>  LogMsgFonts  словарь соответствия типов логов и их шрифтов
        /// 3. Методы класса:
        /// а) protected virtual void OnNewLogMessage(NewLogEventsArgs Args) метод генерирующий рассылку
        ///    событий обработчикам событий.
        /// б) public Logger() конструктор логгера, инициализирует поля класса.
        /// в) public void SetLogTypeColor(LogType LogMsgType, Color LogColor) метод для установка цвета для 
        ///    соответствующего типа событий (LogMsgType).
        /// г) public void SetLogTypeFont(LogType LogMsgType, Font LogFont) метод для установка шрифта для 
        ///    соответствующего типа событий (LogMsgType).
        /// д) public void AddLogMessage(String LogMessage, LogType LogMessageType, Boolean AddSysTime)
        ///    метод для добавления нового лога с типом LogMessageType, атрибуты шрифта и цвета берутся из словарей,
        ///    параметр AddSysTime используется для добавления системного времени (если он равен true).
        /// е) public StringBuilder EditLogMessage(Int32 Index) метод возвращает сообщение лога для его 
        ///    редактирования.
        /// ж) public void DeleteLogMessage(Int32 MsgLogIndex) метод для удаление лога по индексу.
        /// з) public List<TextAttributtes> GetLogs(LogType Type) метод для получения списка логов одного типа,
        ///    задаваемого параметром Type. 
        /// и) public String GetLogMessageText(Int32 MsgLogIndex) метод для получения только текста сообщения
        ///    лога по индексу лога MsgLogIndex.
        /// 4. Свойства и индексаторы класса:
        /// а) public Int32 LastLogMsgIndex свойство только для чтения, возвращает максимальный индекс
        ///    логов.
        /// 5. События
        /// а) public event EventHandler<NewLogEventsArgs> NewLogMessage - событие добавления нового лога,
        /// </описание класса public class Logger>
        public class Logger
        {
            private List<TextAttributtes> Logs = new List<TextAttributtes>();
            private Dictionary<LogType, Color> LogMsgColors = new Dictionary<LogType, Color>();
            private Dictionary<LogType, Font> LogMsgFonts = new Dictionary<LogType, Font>();

            public event EventHandler<NewLogEventsArgs> NewLogMessage;

            protected virtual void OnNewLogMessage(NewLogEventsArgs Args)
            {
                EventHandler<NewLogEventsArgs> Handler = NewLogMessage;
                if (Handler != null) Handler(this, Args);
            }

            public Logger()
            {
                Int32[] LogMsgTypes = (Int32[])Enum.GetValues(typeof(LogType));
                Font DefaultFont = new Font("Times New Roman", 10.0f);
                foreach (Int32 LogMsgType in LogMsgTypes)
                    LogMsgColors[(LogType)LogMsgType] = Color.Black;
                foreach (Int32 LogMsgType in LogMsgTypes)
                    LogMsgFonts[(LogType)LogMsgType] = DefaultFont;
            }

            public void SetLogTypeColor(LogType LogMsgType, Color LogColor)
            {
                LogMsgColors[LogMsgType] = LogColor;
            }

            public void SetLogTypeFont(LogType LogMsgType, Font LogFont)
            {
                LogMsgFonts[LogMsgType] = LogFont;

            }

            public void AddLogMessage(String LogMessage, LogType LogMessageType, Boolean AddSysTime)
            {
                TextAttributtes Log = new TextAttributtes();
                Log.LogText = new StringBuilder(LogMessage);
                Log.TypeOfLog = LogMessageType;
                Log.TextColor = LogMsgColors[LogMessageType];
                Log.FontStyle = LogMsgFonts[LogMessageType];
                Int32 Index = Log.LogText.ToString().IndexOf(Environment.NewLine);
                if (Index < Log.LogText.Length - 2) Log.LogText.Insert(Log.LogText.Length, Environment.NewLine);
                if (AddSysTime)
                {
                    string Time = DateTime.Now.ToString("[d/M/yyyy HH:mm:ss] ");
                    Log.LogText.Insert(0, Time);
                }
                Logs.Add(Log);
                NewLogEventsArgs AddedLog = new NewLogEventsArgs(Log);
                OnNewLogMessage(AddedLog);
            }

            public StringBuilder EditLogMessage(Int32 Index)
            {
                if (Index >= Logs.Count)
                    return null;
                else return Logs[Index].LogText;
            }

            public void DeleteLogMessage(Int32 MsgLogIndex)
            {
                Logs.RemoveAt(MsgLogIndex);
            }

            public List<TextAttributtes> GetLogs(LogType Type)
            {
                var Query = from Log in Logs where Log.TypeOfLog == Type select Log;
                return Query.ToList();
            }

            public String GetLogMessageText(Int32 MsgLogIndex)
            {
                if (MsgLogIndex >= Logs.Count)
                    return String.Empty;
                else return Logs[MsgLogIndex].LogText.ToString();
            }

            public TextAttributtes GetLogMessageTextWithAttributes(Int32 MsgLogIndex)
            {
                if (MsgLogIndex >= Logs.Count)
                    return default(TextAttributtes);
                else return Logs[MsgLogIndex];
            }

            public Int32 LastLogMsgIndex
            {
                get { return Logs.Count - 1; }
            }

        }
    }
}